﻿#pragma once
#ifndef WRARRAY_H
#define WRARRAY_H

#include "../WRBasics.h"
#include <QAtomicInt>
#include <QList>
#include <QVector>
#ifdef WRDEBUG
#include "../Runtime/WRException.h"
#endif

//表示简单数组。
template <class T> class WRArray
{
private:
    //数组数据。
    class Data
    {
    private:
        //指针。
        T* m_arr;
        //数量。
        WRu m_cnt;
        //引用。
        QAtomicInt m_ref;

        //初始化空数量的数据。
        inline Data(void) : m_arr(0), m_cnt(0), m_ref(1)
        {
            //add code here
        }
        //删除当前数据对象。
        inline ~Data()
        {
            if (m_arr)
            {
                delete[] m_arr;
            }
        }

    public:
        //初始化指定元素数量的数据。
        inline explicit Data(WRu count) : m_arr(new T[count]), m_cnt(count), m_ref(1)
        {
            //add code here
        }

        //添加对象引用。
        inline void addRef(void)
        {
            m_ref.ref();
        }
        //释放对象引用, 如果引用计数为0，则删除对象，返回True，否则返回False。
        inline bool release(void)
        {
            if (!m_ref.deref())
            {
                delete this;
                return true;
            }
            return false;
        }

        //获取元素数量。
        inline WRu count(void) const
        {
            return m_cnt;
        }

        //获取数据内容。
        inline const T* array(void) const
        {
            return m_arr;
        }
        //获取数据内容。
        inline T* array(void)
        {
            return m_arr;
        }

        //获取指定起始位置的数据。
        inline const T* array(WRu start) const
        {
#ifdef WRDEBUG
            if (start >= m_cnt)
            {
                throw WRArgumentOutOfRangeException();
            }
#endif
            return m_arr + start;
        }
        //获取指定起始位置的数据。
        inline T* array(WRu start)
        {
#ifdef WRDEBUG
            if (start >= m_cnt)
            {
                throw WRArgumentOutOfRangeException();
            }
#endif
            return m_arr + start;
        }

        //获取指定索引处的元素。
        inline const T& index(WRu index) const
        {
#ifdef WRDEBUG
            if (index >= m_cnt)
            {
                throw WRArgumentOutOfRangeException();
            }
#endif
            return m_arr[index];
        }
        //获取指定索引处的元素。
        inline T& index(WRu index)
        {
#ifdef WRDEBUG
            if (index >= m_cnt)
            {
                throw WRArgumentOutOfRangeException();
            }
#endif
            return m_arr[index];
        }

        //获取空数据。
        static Data* empty(void)
        {
            static Data value;
            value.addRef();
            return &value;
        }
    };
    //数组数据。
    Data* m_data;

public:
    //初始化空数组。
    inline WRArray() : m_data(Data::empty())
    {
        //add code here
    }
    //初始化指定元素数量的数组。
    inline explicit WRArray(WRu count)
        : m_data(count ? new Data(count) : Data::empty())
    {
        //add code here
    }

    //复制构造函数。
    inline WRArray(const WRArray& other) : m_data(other.m_data)
    {
        m_data->addRef();
    }
    //重载赋值操作符。
    inline WRArray& operator =(const WRArray& other)
    {
        if (other.m_data != m_data)
        {
            m_data->release();
            m_data = other.m_data;
            m_data->addRef();
        }
        return *this;
    }

    //移动构造函数。
    inline WRArray(WRArray&& other) : m_data(other.m_data)
    {
        other.m_data=Data::empty();
    }
    //重载移动操作符。
    inline WRArray& operator =(WRArray&& other)
    {
        if (other.m_data != m_data)
        {
            m_data->release();
            m_data = other.m_data;
            other.m_data=Data::empty();
        }
        return *this;
    }

    //从列表中初始化数组。
    template<class T2>
    inline explicit WRArray(const QList<T2>& list)
        : m_data(list.count() ? new Data(list.count()) : Data::empty())
    {
        for(WRu i = 0, l = list.count(); i < l; ++i)
        {
            m_data->index(i) = list[(int)i];
        }
    }
    //重载赋值操作符。
    template<class T2>
    inline WRArray& operator =(const QList<T2>& list)
    {        
        m_data->release();
        if (list.count())
        {
            m_data = new Data(list.count());
            for(WRu i = 0, l = list.count(); i < l; ++i)
            {
                m_data->index(i) = list[(int)i];
            }
        }
        else
        {
            m_data = Data::empty();
        }
        return *this;
    }

    //从列表中初始化数组。
    template<class T2>
    inline explicit WRArray(const QVector<T2>& list)
        : m_data(list.count() ? new Data(list.count()) : Data::empty())
    {
        for(WRu i = 0, l = list.count(); i < l; ++i)
        {
            m_data->index(i) = list[i];
        }
    }
    //重载赋值操作符。
    template<class T2>
    inline WRArray& operator =(const QVector<T2>& list)
    {
        m_data->release();
        if (list.count())
        {
            m_data = new Data(list.count());
            for(WRu i = 0, l = list.count(); i < l; ++i)
            {
                m_data->index(i) = list[i];
            }
        }
        else
        {
            m_data = Data::empty();
        }
        return *this;
    }

    //删除当前数组对象。
    inline ~WRArray()
    {
        m_data->release();
    }

    //获取元素数量。
    inline WRu count(void) const
    {
        return m_data->count();
    }

    //获取指定索引处的元素。
    inline const T& index(WRu index) const
    {
        return m_data->index(index);
    }
    //获取指定索引处的元素。
    inline T& index(WRu index)
    {
        return m_data->index(index);
    }

    //获取指定索引处的元素。
    inline const T& operator[](WRu index) const
    {
        return m_data->index(index);
    }
    //获取指定索引处的元素。
    inline T& operator[](WRu index)
    {
        return m_data->index(index);
    }

    //判断当前对象是否和指定的对象指向相同的地址。
    inline bool equals(const WRArray& other) const
    {
        return m_data == other.m_data;
    }

    //判断当前对象是否和指定的对象指向相同的地址。
    inline bool operator==(const WRArray& other) const
    {
        return m_data == other.m_data;
    }
    //判断当前对象是否和指定的对象指向不同的地址。
    inline bool operator!=(const WRArray& other) const
    {
        return m_data != other.m_data;
    }

    //获取空数组。
    static const WRArray<T>& empty(void)
    {
        static WRArray<T> value;
        return value;
    }
};
#endif // WRARRAY_H
